import os
import glob
from datetime import datetime
import shutil
import winreg

# 获取今天的日期并格式化为文件名格式
today = datetime.now().strftime("%Y_%m_%d")
# 获取日志目录下所有日志文件
log_files = glob.glob("../e:/bc/bilibili_cheers-master/log/*.log")

for log_file in log_files:
    # 检查文件名是否不是今天的日志文件
    if today not in log_file:
        os.remove(log_file)

from PySide6.QtCore import (QCoreApplication, QMetaObject, QRect,
                            QSize, Qt, QStringListModel, QThread, Signal)
from PySide6.QtGui import (QAction)
from PySide6.QtWidgets import (QCheckBox, QComboBox, QGroupBox,
                               QHBoxLayout, QLabel, QLineEdit, QListView,
                               QMenu, QMenuBar, QPushButton,
                               QSizePolicy, QSpacerItem, QStatusBar, QVBoxLayout,
                               QWidget)
from PySide6.QtWidgets import QApplication, QMainWindow

from ui.zck import Ui_MainWindow
from config_utils import 读取配置文件, 写入配置文件

import sys
from common.settings import ROOT_PATH, logger, 临时目录, 保存目录, 删除临时文件, 关闭浏览器, 分辨率配置, 定位文本, 运行端口
import os
from PySide6.QtWidgets import QFileDialog
from config_utils import 写入配置文件, 读取配置文件
from hqsj import hqwyxx
import time
from utils.bilibili_control import BilibiliHandler


# 1. 定义下载线程类（PySide6版本）
class DownloadThread(QThread):
    # 定义信号（PySide6中使用Signal）
    log_signal = Signal(str)  # 发送日志信息
    finish_signal = Signal()  # 通知下载完成

    def __init__(self, url, total_episodes, start_episode=1):
        super().__init__()
        self.url = url
        self.total_episodes = total_episodes
        self.start_episode = start_episode

    def run(self):
        # 子线程中执行下载任务
        i = self.start_episode
        j_wzq = self.url.split('?')[0]
        while i < self.total_episodes + 1:
            j_wz = j_wzq + f'?p={i}'
            # 发送日志到主线程
            self.log_signal.emit(f"第 {i} 个视频的实际网址：{j_wz}\n开始下载第 {i} 个视频！")

            # 执行下载
            bilibili = BilibiliHandler(j_wz)
            bilibili.run()

            # 发送完成日志到主线程
            self.log_signal.emit(f"第 {i} 个视频已完成！")

            i += 1
            time.sleep(3)

        # 通知下载全部完成
        self.finish_signal.emit()




class 子程序初始化(Ui_MainWindow):
    def __init__(self, MainWindow):
        super().__init__()
        self.setupUi(MainWindow)
        # 1. 在这里设置主窗口标题（MainWindow是主窗口实例）
        MainWindow.setWindowTitle("bilibili多集视频批量下载器 V1.0")
        self.子程序_初始化()

    def 子程序_初始化(self):


        self.临时目录 = 临时目录
        self.保存目录 = 保存目录

        # 初始化分辨率配置
        if 分辨率配置:
            for key, value in 分辨率配置.items():
                try:
                    display_text, item_value = value.split(',')
                    self.xlzhk_qxd.addItem(display_text, item_value)
                except Exception as e:
                    print(f"❌ 分辨率配置解析失败：{e}")
        else:
            print("❌ 分辨率配置为空，无法初始化选项！")

        # 初始化其他
        self.bjk_lsml.setText(临时目录)
        self.bjk_bcml.setText(保存目录)
        self.xzk_sqlswj.setChecked(删除临时文件)
        self.xzk_gbllq.setChecked(关闭浏览器)
        self.lb_yxrz.setEditTriggers(QListView.EditTrigger.NoEditTriggers)  # 禁止编辑
        
        # 初始化 list_model
        self.list_model = QStringListModel()
        self.lb_yxrz.setModel(self.list_model)
        
        # 清理日志文件
        log_dir = os.path.join(os.path.dirname(__file__), "log")
        self.清理日志文件(log_dir)
        

        # self.lb_yxzwj.setEditTriggers(QListView.EditTrigger.NoEditTriggers)  # 禁止编辑
        # self.lb_yxzwj.setSelectionMode(QListView.SelectionMode.SingleSelection)  # 单选
         # 双击事件


        # 绑定事件
        self.an_lsml.clicked.connect(self.子程序_临时目录)
        self.an_bcml.clicked.connect(self.子程序_保存目录)
        self.an_zddq.clicked.connect(self.子程序_自动读取)
        # self.an_xlj.clicked.connect(self.子程序_写路径)
        self.xzk_sqlswj.stateChanged.connect(self.子程序_保存配置)
        self.xzk_gbllq.stateChanged.connect(self.子程序_保存配置)
        self.pushButton_4.clicked.connect(self.子程序_开始下载)
        # self.lb_yxzwj.doubleClicked.connect(self.子程序_播放)
        
        # 绑定关于我的弹出窗口
        self.action_3.triggered.connect(self.子程序_关于我)
        self.action.triggered.connect(self.子程序_打开帮助)

    def 子程序_打开帮助(self):
        # 打开帮助文档
        help_file = os.path.join(ROOT_PATH, "bilibili多集视频批量下载使用方法.html")
        if os.path.exists(help_file):
            os.startfile(help_file)


    def 清理日志文件(self, log_dir):
        """
        删除指定目录中除今天日期之外的所有日志文件
        日志文件命名格式要求: YYYY_MM_DD.log (例如: 2025_09_24.log)
        """
        # 获取今天的日期字符串，格式与日志文件一致 (YYYY_MM_DD)
        today = datetime.now().strftime("%Y_%m_%d")

        # 检查目录是否存在
        if not os.path.exists(log_dir):
            print(f"日志目录不存在: {log_dir}")
            return

        # 遍历目录中的所有文件
        for filename in os.listdir(log_dir):
            # 拼接完整文件路径
            file_path = os.path.join(log_dir, filename)

            # 只处理文件，跳过目录
            if not os.path.isfile(file_path):
                continue

            # 检查文件名是否符合日志文件格式 (YYYY_MM_DD.log)
            if len(filename) != 14 or not filename.endswith(".log"):
                continue  # 不符合格式的文件不处理

            # 提取文件名中的日期部分 (去除 .log 后缀)
            date_str = filename[:-4]

            # 检查日期格式是否正确
            try:
                # 尝试解析日期，验证格式是否为 YYYY_MM_DD
                datetime.strptime(date_str, "%Y_%m_%d")
            except ValueError:
                continue  # 日期格式不正确的文件不处理

            # 如果不是今天的日志文件，则删除
            if date_str != today:
                try:
                    os.remove(file_path)
                    print(f"已删除过期日志: {file_path}")
                except Exception as e:
                    print(f"删除日志失败 {file_path}: {str(e)}")

    def 子程序_清空列表(self):
        self.list_model = QStringListModel()  # 数据模型
        self.lb_yxrz.setModel(self.list_model)
        # self.lb_yxzwj.setStringList([])

        # self.list_model2 = QStringListModel()  # 数据模型
        # self.lb_yxzwj.setModel(self.list_model2)
        # self.list_model.setStringList([])

    def 子程序_加入列表(self, text): #c_lb 日志|保存

        # 获取当前列表所有项
        current_items = self.list_model.stringList()
        # 在列表末尾添加新项
        current_items.insert(0, text)
        # current_items.append(text)
        # 更新模型数据（刷新视图）
        self.list_model.setStringList(current_items)
        # else:
        #     # 获取当前列表所有项
        #     current_items = self.list_model2.stringList()
        #     # 在列表末尾添加新项
        #     current_items.append(text)
        #     # 更新模型数据（刷新视图）
        #     self.list_model2.setStringList(current_items)

    def 子程序_保存配置(self):
        self._写入配置()

    def _写入配置(self, 临时目录=None, 保存目录=None):
        from config_utils import 写入配置文件, 读取配置文件
        
        现有配置 = 读取配置文件()
        配置 = {
            "临时目录": 临时目录 if 临时目录 is not None else 现有配置.get("配置", {}).get("临时目录", ""),
            "保存目录": 保存目录 if 保存目录 is not None else 现有配置.get("配置", {}).get("保存目录", ""),
            "删除临时文件": "是" if self.xzk_sqlswj.isChecked() else "否",
            "关闭浏览器": "是" if self.xzk_gbllq.isChecked() else "否",
            "定位文本": 现有配置.get("配置", {}).get("定位文本", "")
        }
        
        写入配置文件({
            "配置": 配置,
            "分辨率": 现有配置.get("分辨率", {})
        })

    def 子程序_临时目录(self):
        # from common.settings import 临时目录
        # 打开目录选择对话框
        directory = QFileDialog.getExistingDirectory(None, "选择临时目录", self.临时目录)
        if directory:
            # 验证目录
            if os.path.isdir(directory):
                # 更新配置和界面
                self.临时目录 = directory
                self.bjk_lsml.setText(self.临时目录)
                self._写入配置(临时目录=self.临时目录)
            else:
                print("❌ 目录无效！")

    def 子程序_保存目录(self):
        # from common.settings import 保存目录
        # 打开目录选择对话框
        directory = QFileDialog.getExistingDirectory(None, "选择保存目录", self.保存目录)
        if directory:
            # 验证目录
            if os.path.isdir(directory):
                # 更新配置和界面
                self.保存目录 = directory
                self.bjk_bcml.setText(self.保存目录)
                self._写入配置(保存目录=self.保存目录)
            else:
                print("❌ 目录无效！")

    def 子程序_自动读取(self):

        self.子程序_清空列表()
        # 调用 hqwyxx 类
        hq = hqwyxx()
        if hq.result:
            self.cookies = self.子程序_处理cookies(hq.cookies)
            # self.cookies = hq.cookies

            self.total_episodes = hq.total_episodes
            if self.total_episodes is None:
                self.total_episodes = 1
            self.current_url = hq.current_url
            # print(f"✅ 自动读取完成：cookies:  {self.cookies}, \n总集数={self.total_episodes}, \n当前网址={self.current_url}")
            self.子程序_加入列表( f"✅ 自动读取完成： \n cookies:  {self.cookies}, \n总集数={self.total_episodes}, \n当前网址={self.current_url}")
        else:
            print("❌ 自动读取失败！")
            self.子程序_加入列表( "❌ 自动读取失败！")

        self.bjk_wz.setText(self.current_url)
        self.bjk_zjs.setText(str(self.total_episodes))
        self.bjk_ksjs.setText("1")
        self.bjk_jsjs.setText(str(self.total_episodes))
        
        # 处理 cookies 为列表的情况
        if isinstance(hq.cookies, list):
            for cookie in hq.cookies:
                if cookie.get('name') == 'CURRENT_QUALITY':
                    局清晰度 = cookie.get('value')
                    print(f"✅ 当前清晰度：{str(局清晰度)}")
                    
                    # 根据局清晰度的值选择 xlzhk_qxd 中的选项
                    for index in range(self.xlzhk_qxd.count()):
                        item_value = self.xlzhk_qxd.itemData(index)
                        if item_value == 局清晰度:
                            self.xlzhk_qxd.setCurrentIndex(index)
                            print(f"✅ 已选择清晰度选项：{self.xlzhk_qxd.itemText(index)}")
                            break
                    else:
                        print("❌ 未找到匹配的清晰度选项！")
                    break
            else:
                print("❌ 未找到清晰度信息！")

    def 子程序_处理cookies(self, new_cookie_list):
        from enum import Enum
        # 2. 定义需要提取的 Cookie 名称（按你需要的顺序）
        target_cookie_names = ['CURRENT_QUALITY', 'buvid3', 'SESSDATA']
        # 存储最终的 键=值 字符串列表
        formatted_cookies = []

        # 3. 遍历筛选并格式化 Cookie
        for cookie in new_cookie_list:
            cookie_name = cookie.get('name')
            # 只处理目标 Cookie
            if cookie_name not in target_cookie_names:
                continue

            # 特殊处理 SESSDATA：优先选择 domain 为 .bilibili.com 的（避免重复）
            if cookie_name == 'SESSDATA' and cookie.get('domain') != '.bilibili.com':
                continue

            # 转为 "键=值" 格式，加入列表
            formatted_cookies.append(f"{cookie_name}={cookie.get('value')}")
            # 已找到一个目标 Cookie，从列表中移除（避免重复处理）
            target_cookie_names.remove(cookie_name)

            # 若三个目标都找到，提前退出循环（提高效率）
            if not target_cookie_names:
                break

        # 4. 用分号连接，得到最终 Cookie 字符串
        final_cookie_str = '; '.join(formatted_cookies)
        print(final_cookie_str)

        # 输出示例：CURRENT_QUALITY=80; buvid3=4AEA8F0E-964F-00F3-A57A-86F0B1FDDF5833614infoc; SESSDATA=47829266%2C1774055756%2Cecf08%2A91CjDSrmbwQOFelyx4G1_utFY-EcSQ-7eipwg0PlG-ngIM1rx3TNKCVaWPsx2E2GnSC-wSVnJ3dGJJMTBZSUlMNjB4cDBwVklYVTFvZElCZXMxbDNvNkxEVWVaTS1EbXFyMzh4RTdLSlF6bnptTG1qVWZJcFp1QlBsdnBUdGxCbEdIU2N3UmROcVJ3IIEC

        # 5. 更新 constant.py 中的 RequestHeaders.COOKIE（在其他文件中调用时）
        class RequestHeaders(Enum):
            j_qxd = '32'  # 保持原配置
            REFERER = 'https://t.bilibili.com/?spm_id_from=333.788.0.0'
            USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36'
            COOKIE = final_cookie_str  # 替换为新生成的 Cookie 字符串
        return final_cookie_str


    def 子程序_开始下载(self):
        # 确保 list_model 已初始化
        if not hasattr(self, 'list_model'):
            self.list_model = QStringListModel()
            self.lb_yxrz.setModel(self.list_model)
            
        # 检查 current_url 和 total_episodes 是否有效
        if not hasattr(self, 'current_url') or not self.current_url or len(self.current_url) <= 30:
            self.子程序_加入列表("❌ 当前网址无效，请先执行自动读取或手动输入！")
            return
        
        if not hasattr(self, 'total_episodes') or not self.total_episodes:
            self.子程序_加入列表("❌ 总集数无效，请先执行自动读取或手动输入！")
            return
        
        # 获取开始下载集数
        try:
            bjk_ksjs = int(self.bjk_ksjs.text())
            self.total_episodes = int(self.bjk_jsjs.text())
            if bjk_ksjs > int(self.total_episodes):
                self.子程序_加入列表(f"❌ 开始集数 {bjk_ksjs} 不能大于总集数 {self.total_episodes}！")
                return
        except ValueError:
            self.子程序_加入列表("❌ 开始集数无效，请输入数字！")
            return
        
        # 创建并启动下载线程
        self.download_thread = DownloadThread(
            self.current_url,
            int(self.total_episodes),
            int(self.bjk_ksjs.text())
        )
        # 连接信号与槽函数
        self.download_thread.log_signal.connect(self.子程序_加入列表)
        self.download_thread.finish_signal.connect(self.子程序_加入列表)
        self.download_thread.start()  # 启动线程

    def 子程序_关于我(self):
        """
        显示关于我的弹出窗口
        """
        from PySide6.QtWidgets import QMessageBox
        
        # 设置弹出窗口内容
        about_text = (
            "版本：bilibili多集视频批量下载 V1.0\n"
            "开发者：称砣VS轻羽\n"
            "联系方式：85189930@qq.com\n\n"
            "免责声明：\n"
            "1.本软件仅用于技术学习与研究不得对外出售和任何商业用途，不提供任何知识产权许可，用户需遵守视频原版权方（如哔哩哔哩）协议及法律法规。\n"
            "2.通过本软件下载的视频，仅限个人学习使用，须在 24 小时内主动删除，严禁用于商业、传播等侵权行为。\n"
            "3.用户使用软件的所有操作及后果由自身承担，开发者不对任何因使用软件导致的侵权、违法等行为及损失承担连带责任。\n"
            "4.软件不保证兼容性、稳定性及安全性，用户应自行评估使用风险。\n"
            "5.您下载、使用本软件，即视为接受本声明全部条款；若不同意，请勿使用。\n"
        )
        
        # 显示弹出窗口
        QMessageBox.information(
            None,
            "关于",
            about_text,
            QMessageBox.StandardButton.Ok
        )

    def 子程序_写路径(self):

        """
        处理FFmpeg相关路径配置：
        1. 检查系统环境变量Path是否包含目标FFmpeg路径，不包含则添加
        2. 检查FFmpeg文件夹是否存在，不存在则从项目目录复制
        """
        # 目标FFmpeg路径
        ffmpeg_target_path = "D:\\Program Files\\ffmpeg-7.1.1-essentials_build\\bin"
        # 项目中FFmpeg源目录（假设在项目根目录下）
        project_ffmpeg_dir = os.path.join(ROOT_PATH, "ffmpeg-7.1.1-essentials_build")

        # 步骤1：检查并复制FFmpeg文件夹（如果不存在）
        self._check_and_copy_ffmpeg(ffmpeg_target_path, project_ffmpeg_dir)

        # 步骤2：检查并添加环境变量
        self._check_and_add_env_path(ffmpeg_target_path)

    def _check_and_copy_ffmpeg(self, target_path, source_dir):
        """检查目标FFmpeg文件夹是否存在，不存在则从项目复制"""
        # 提取目标目录（bin的上级目录）
        target_dir = os.path.dirname(target_path)

        if not os.path.exists(target_dir):
            print(f"FFmpeg目录不存在，开始从项目复制到 {target_dir}")

            # 检查项目源目录是否存在
            if not os.path.exists(source_dir):
                raise FileNotFoundError(f"项目中的FFmpeg目录不存在：{source_dir}")

            try:
                # 复制整个目录（包括子文件和子目录）
                shutil.copytree(
                    source_dir,
                    target_dir,
                    dirs_exist_ok=True  # 允许目标目录存在时覆盖（Python 3.8+支持）
                )
                print(f"FFmpeg目录复制成功：{target_dir}")
            except Exception as e:
                raise RuntimeError(f"复制FFmpeg目录失败：{str(e)}")
        else:
            print(f"FFmpeg目录已存在：{target_dir}")

    def _check_and_add_env_path(self, ffmpeg_path):
        """检查系统环境变量Path是否包含目标路径，不包含则添加"""
        try:
            # 打开系统环境变量注册表（需要管理员权限）
            with winreg.OpenKey(
                    winreg.HKEY_LOCAL_MACHINE,
                    r"SYSTEM\CurrentControlSet\Control\Session Manager\Environment",
                    0,
                    winreg.KEY_READ | winreg.KEY_WRITE
            ) as key:

                # 读取当前Path值
                current_path, _ = winreg.QueryValueEx(key, "Path")
                path_list = current_path.split(';')

                # 检查目标路径是否已在Path中（忽略大小写）
                if not any(p.strip().lower() == ffmpeg_path.lower() for p in path_list):
                    print(f"FFmpeg路径不在环境变量中，开始添加：{ffmpeg_path}")

                    # 添加新路径（用;分隔）
                    new_path = current_path + ';' + ffmpeg_path
                    winreg.SetValueEx(key, "Path", 0, winreg.REG_EXPAND_SZ, new_path)
                    print("环境变量Path更新成功")

                    # 提示：环境变量更新需要重启程序生效
                    print("注意：环境变量更新需要重启程序或系统才能生效")
                else:
                    print(f"FFmpeg路径已在环境变量中：{ffmpeg_path}")

        except PermissionError:
            raise PermissionError("操作失败：需要以管理员权限运行程序才能修改系统环境变量")
        except Exception as e:
            raise RuntimeError(f"操作环境变量失败：{str(e)}")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    MainWindow = QMainWindow()
    ui = 子程序初始化(MainWindow)
    MainWindow.show()
    sys.exit(app.exec())
